﻿using LitJson;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;

public class Part : Item
{
    public Vector2Int m_PartPos = new Vector2Int(0, 0);
    public HexGrid.RotationAngle m_RotationAngle = HexGrid.RotationAngle.NONE;
    public int m_ID = -1;// 用于在舰船中找到指定的部件
    bool m_IsEnabled = true;

    public List<Vector2Int> m_OccupyGrads = new List<Vector2Int>();
    public float initAngle { get { return m_InitAngle; } }
    public bool isEnabled {
        set { m_IsEnabled = value; }
        get { return m_IsEnabled; }
    }
    int[] m_PartShape;
    protected float m_InitAngle = 0;
    public Part()
    {
        m_PartShape = null;
    }
    public HexGrid GetShape(int index, bool isRotate = true)
    {
        if (m_PartShape == null|| index < 0)
            return new HexGrid(m_PartPos);
        var i = m_PartShape[index];
        var indexRadius = Part.GetRadius(i);
        var indexCount = Part.GetIndexCount(indexRadius - 1);


        var hexGridCenter = new HexGrid(m_PartPos.x, m_PartPos.y);
        var hexGrid = HexGrid.GetRing(new HexGrid(m_PartPos.x, m_PartPos.y), indexRadius, i - indexCount);
        var hexIncrease = hexGrid - hexGridCenter;
        if (isRotate)
            hexIncrease.Rotation(m_RotationAngle);
        hexGridCenter = hexGridCenter + hexIncrease;
        var realPos = hexGridCenter.GetPositionOddr();
        return hexGridCenter;
    }
    public int GetNumShape()
    {
        if (m_PartShape == null)
            return 0;
        return m_PartShape.Length;
    }

    public struct ShapeInformation 
    {
        public Vector2 size;
        public Vector2 pivot;
        public Vector2 startPoint;//    整个形状矩形化的左下角
    }

    //  \brief 返回形状的二维尺寸和中心点在形状中的位置比。单位是：1单位的六边形半径
    //  x,y是二维尺寸， z,w是中心点的位置比（范围：0-1）
    public ShapeInformation GetShapeInfo(float radius = 1, bool isRotate = true)
    {
        var theCenter = new HexGrid(m_PartPos.x, m_PartPos.y);
        HexGrid minX = theCenter;
        HexGrid maxX = theCenter;
        HexGrid minY = theCenter;
        HexGrid maxY = theCenter;
        int numShape = GetNumShape();
        if (m_PartShape == null)
            numShape = 1;
        for (int i = 0; i < numShape; ++i)
        {
            var hexPos = GetShape(i, isRotate);
            if (hexPos.GetPosition().x >= maxX.GetPosition().x)
            {
                if(hexPos.GetPosition().x == maxX.GetPosition().x)
                {
                    if (hexPos.GetPosition().z < maxX.GetPosition().z)
                        maxX = hexPos;
                }
                else
                    maxX = hexPos;
            }
            if (hexPos.GetPosition().x <= minX.GetPosition().x)
            {
                if (hexPos.GetPosition().x == minX.GetPosition().x)
                {
                    if (hexPos.GetPosition().z > minX.GetPosition().z)
                        minX = hexPos;
                }
                else
                    minX = hexPos;
            }
            if (hexPos.GetPosition().y > maxY.GetPosition().y)
            {
                maxY = hexPos;
            }
            if (hexPos.GetPosition().y < minY.GetPosition().y)
            {
                minY = hexPos;
            }
        }
        var maxXPos = maxX.GetDescartesPosition(radius).x;
        var minXPos = minX.GetDescartesPosition(radius).x;

        var maxYPos = minY.GetDescartesPosition(radius).y;// 因为正Y是向下的，所以这里反转一下
        var minYPos = maxY.GetDescartesPosition(radius).y; 
        //float gradXDifference = maxXPos > minXPos ? (maxXPos - minXPos) : (minXPos - maxXPos);
        //float gradYDifference = maxYPos > minYPos ? (maxYPos - minYPos) : (minYPos - maxYPos);
        float gradXDifference = (maxXPos - minXPos);
        float gradYDifference = (maxYPos - minYPos);

        float widthHex = Mathf.Sqrt(3f);
        ShapeInformation shapeInfo = new ShapeInformation();
        shapeInfo.size = new Vector2(gradXDifference + widthHex, gradYDifference + 2);
        var centerPos = theCenter.GetDescartesPosition(radius);
        shapeInfo.startPoint = new Vector2(minXPos - widthHex / 2f, minYPos - 1);
        centerPos.x = centerPos.x - shapeInfo.startPoint.x;
        centerPos.y = centerPos.y - shapeInfo.startPoint.y;
        shapeInfo.pivot = new Vector2(centerPos.x / shapeInfo.size.x, 1f - centerPos.y / shapeInfo.size.y);//   因为这里算出来的比值是从上到下的，但外面要用的是从下到上，所以反转一下
        return shapeInfo;
    }
    public override void Copy(Item item)
    {
        base.Copy(item);
        Part part = item as Part;
        if (part == null)
            return;

        m_IsEnabled = part.m_IsEnabled;
        mass = part.mass;
        m_PartPos = part.m_PartPos;
        if (part.m_PartShape != null)
            m_PartShape = (int[])part.m_PartShape.Clone();
        else
            m_PartShape = null;
        m_RotationAngle = part.m_RotationAngle;
        part.m_OccupyGrads.ForEach(i => m_OccupyGrads.Add(i));
    }
    public int GetRadius()
    {
        if (m_PartShape == null)
            return 0;
        int maxValue = 0;
        for(int i=0; i<m_PartShape.Length; ++i)
        {
            if(m_PartShape[i]> maxValue)
            {
                maxValue = m_PartShape[i];
            }
        }
        return GetRadius(maxValue);
    }
    public static int GetRadius(int index)
    {
        var radius = Mathf.Sqrt(0.25f + 2f * ((float)index / 6f)) - 0.5f;
        return (int)radius+1;
    }
    public static int GetIndexCount(int radius)
    {
        return (int)(radius / 2f * (radius + 1f)) * 6;
    }

    public virtual List<string> GetParameterList()
    {
        var list = new List<string>();

        for (int i = 0; i < GetParameterNumber(); ++i)
        {
            var name = GetParameterName(i);
            list.Add(name);
        }
        return list;
    }
    public virtual void SetParameter(BehaviourMate behaviour)
    {
        return ;
    }
    public virtual BehaviourMate GetDefaultInfoOfParameter(int type)
    {
        return null;
    }
    public virtual int GetParameterNumber()
    {
        return -1;
    }

    public virtual string GetParameterName(int type)
    {
        string name = "无";
        return name;
    }
    public override void LoadPrefab(JsonData json)
    {
        base.LoadPrefab(json);
        IDictionary<string, JsonData> jsond = json.ValueAsObject();
        if (jsond.ContainsKey("PartShape") && jsond["PartShape"].Count >= 1)
        {
            m_PartShape = new int[jsond["PartShape"].Count];
            for (int i = 0; i < jsond["PartShape"].Count; ++i)
            {
                m_PartShape[i] = jsond["PartShape"][i].ValueAsInt();
            }
        }
        else
            m_PartShape = null;
    }
    public override JsonData Save()
    {
        JsonData root = base.Save();
        root["ID"] = m_ID;
        root["PartPosX"] = m_PartPos.x;
        root["PartPosY"] = m_PartPos.y;
        root["RotationAngle"] = (int)m_RotationAngle;
        return root;
    }

    public override bool Load(JsonData json)
    {
        base.Load(json);
        IDictionary<string, JsonData> jsond = json.ValueAsObject();

        if (jsond.ContainsKey("ID"))
            m_ID = jsond["ID"].ValueAsInt();
        if (jsond.ContainsKey("PartPosX") && jsond.ContainsKey("PartPosY"))
            m_PartPos = new Vector2Int(jsond["PartPosX"].ValueAsInt(), jsond["PartPosY"].ValueAsInt());
        if (jsond.ContainsKey("RotationAngle"))
            m_RotationAngle = (HexGrid.RotationAngle)jsond["RotationAngle"].ValueAsInt();
        return true;
    }
}
 